<?php

/**
 * 余外海库 SDK
 * @author chenyun
 */

namespace App\Service\VendorClient\Shophaiku;
use App\Model\PssModel\ServiceConfig;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;

class ShophaikuApiClient
{
    private $account  = 'Shophaiku';
    protected $config;
    protected $RouteMap = [
        'createOrder'   => 'ecm_deliveryorder_create',
        'cancelOrder'   => 'ecm_order_cancel',
    ];
    
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];
        
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        
        //商品下单组
        $orderLineXml = '';
        $productAmt   = 0 ;
        foreach ($params['orderGoods'] as $key => $item ) 
        {
           //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity ;
            
            //商品单价包含税金
            if( $key == 0 ) {
                $dev_money = bcdiv((string)$deliver_money, (string)$quantity,2);
                $price = bcadd((string)$price, (string)$dev_money,2);
            }
            
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            
            //商品总价
            $totalSingleGoodsPrice = bcmul((string)$buyAcount,(string)$singleGoodsPrice,2);
            //商品组
            $orderLineXml.= $this->arrToXml([
                 'orderLine'    => $this->arrToXml([
                     'itemCode'     => $item['supplier_skucode'],
                     'planQty'      => $buyAcount,
                     'actualPrice'  => (float)$singleGoodsPrice,
                 ])
             ]);
            $productAmt = bcadd((string)$productAmt,(string)$totalSingleGoodsPrice,2);
        }

        //实际下单金额 
        $real_total_money   = $orderInfo['real_total_money'];
        //订单总金额 = 不含税商品总金额 + 总税费 + 运费 - 优惠金额
        $ActualPaidAmt      = bcadd((string)$productAmt,(string)'0.00',2);
        //优惠金额
        $discount_money     = bcsub((string)$ActualPaidAmt,$real_total_money,2);
        //支付时间
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$pay_time);
        //支付流水号
        $pay_sn             = $order['paySerial'] ?? $orderInfo['pay_sn'];
        //下单支付的时候支付信息
        $apply_extends      = @json_decode($orderInfo['apply_extends'],true);
      
        //获取上游供应商支付方式路由
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $payCommanyName = $apply_extends['payCommanyName'] ?? '';
        $PayCompanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;
        $payCommanyName = $order['payCommanyName'] ? $order['payCommanyName'] : $payCommanyName;
        $pay_value      = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_PAY, $PayCompanyCode);
        if (empty($pay_value)) {
            return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$PayCompanyCode}】未映射，请联系管理员处理");
        } 
        
        //电商平台信息
        $enterpriseNum  = $apply_extends['enterpriseNum'] ?? '';
        $enterpriseName = $apply_extends['enterpriseName'] ?? '';
        $enterpriseNum  = $order['enterpriseNum'] ? $order['enterpriseNum'] : $enterpriseNum;
        $enterpriseName = $order['enterpriseName'] ? $order['enterpriseName'] : $enterpriseName;
        
        //获取电商平台映射配置
        $channel_value = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_CHANNEL, $enterpriseNum);
        if( empty($channel_value) ) {
            return Normal::returnCode(Normal::FAIL,"支付电商平台编码：【{$enterpriseNum}】未映射，请联系管理员处理");
        }
        
        //创建订单数据
        $receiverInfo = [
            'name'              => $orderInfo['receive_name'],
            'mobile'            => $orderInfo['recveive_phone'],
            'province'          => $orderInfo['province'],
            'city'              => $orderInfo['city'],
            'area'              => $orderInfo['district'],
            'detailAddress'     => $orderInfo['receive_address'],
        ];
        
        $deliveryOrder = [
            'deliveryOrderCode'             => $orderInfo['supplier_dsn'],
            'orderType'                     => "JYCK",
            'warehouseCode'                 => "OTHER",
            'sourcePlatformCode'            => $channel_value,
            'sourcePlatformName'            => $enterpriseName,
            'createTime'                    => date("Y-m-d H:i:s",time()),
            'payTime'                       => $pay_time,
            'payNo'                         => $pay_sn,
            'shopNick'                      => $this->config['shopNick'],
            'totalAmount'                   => (float)$ActualPaidAmt,
            'itemAmount'                    => (float)$real_total_money,
            'discountAmount'                => $discount_money,
            'freight'                       => '0.00',
            'receiverInfo'                  => $this->arrToXml($receiverInfo),
            'buyerName'                     => $orderInfo['buyer_realname'],
            'buyerIdType'                   => 1,
            'buyerIdNumber'                 => $orderInfo['buyer_idcard'],
            'buyerTel'                      => $orderInfo['buyer_phone'],
            'orderTaxAmount'                => '0.00',
            'payCompanyCode'                => $pay_value,
        ];
        
        $requestXml="";
        $deliveryOrderXml = $this->arrToXml(['deliveryOrder'=>$this->arrToXml($deliveryOrder)]);
        $orderLinesXml = $this->arrToXml(['orderLines'=>$orderLineXml]);
        $requestXml = $this->arrToXml([
            'request'   => $deliveryOrderXml.$orderLinesXml
        ]);
        
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => $requestXml
        ];
        
        $res = $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            return Normal::returnCode(Normal::SUC,"订单推送成功");
        }
        return $res;
    }
    
    /**
     * 组装xml
     */
    public function arrToXml(  $params = [] )
    {
        $xml = '';
        foreach ($params as $key=>$val){
            $xml .= "<{$key}>{$val}</{$key}>";
        }
        return $xml;
    }
    /**
     * 加签
     * @param array $param
     */
    protected function getSign()
    {
        //MD5(userid + 密码 + timestamp)
        $timestamp=date("Y-m-d H:i:s",time());
        $userid=$this->config["userid"];
        $userpwd=$this->config["userpwd"];
        $Sign=md5($userid.$userpwd.$timestamp);
        return "&userid=".$userid."&timestamp=".urlencode($timestamp)."&sign=".$Sign;
    }
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
        ini_set('serialize_precision', 16);
        if( empty($params['supplierOrder'])) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder ");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        //商品下单组
        $goodsDetailXml = $this->arrToXml(['Detail'=>""]);
        $data = [
            'warehouseCode'       => "OTHER",
            'orderCode'           => $orderInfo['supplier_dsn'],
            'orderType'           => "JYCK"
        ];
        $requestXml = $this->arrToXml([
            'request'   =>  $this->arrToXml($data)
        ]);
        $requestParam = [
            'method'    => 'cancelOrder',
            'data'      => $requestXml
        ];

        return $this->execute($requestParam);
    }
    
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        
        $method = $param['method'];

        $url = $this->config["baseurl"]."?msgtype=".$this->RouteMap[$method].$this->getSign();
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'xml',
                'header'    => [
                    "Content-Type:application/xml"
                ],
        
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $xmlObj  = @simplexml_load_string($res,"SimpleXMLElement", LIBXML_NOCDATA);
        if( empty($xmlObj) ) {
            return  Normal::returnCode(Normal::FAIL,"上游接口数据解析异常【{$res}】");
        }
        $jsonStr = json_encode($xmlObj);
        $resHttp = json_decode($jsonStr, true);
        
        if( isset($resHttp['success']) && $resHttp['success'] == "true" ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp);
        }
        $message = isset($resHttp['errormsg']) ? $resHttp['errormsg'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}